#include "stdafx.h"
#include "ui_gdiplus_image_manager.h"


#include <GdiPlus.h>
#pragma comment(lib, "GdiPlus.lib")

_SSL_BEGIN
_SSUIL_BEGIN


static
Gdiplus::Image* load_image_from_memory(const unsigned char *file_buffer, size_t file_buffer_size)
{
	HGLOBAL global_handle = NULL;
	LPVOID global_buffer = NULL;
	IStream *stream = NULL;
	Gdiplus::Image* image = NULL;

	global_handle = GlobalAlloc(GMEM_MOVEABLE, file_buffer_size);
	if(global_handle == NULL)
		goto finish;

	global_buffer = GlobalLock(global_handle);
	if(global_buffer == NULL)
		goto finish;
	memcpy(global_buffer, file_buffer, file_buffer_size);
	GlobalUnlock(global_handle);
	global_buffer = NULL;

	if(!SUCCEEDED(CreateStreamOnHGlobal(global_handle, TRUE, &stream)))
		goto finish;
	global_handle = NULL;

	image = Gdiplus::Image::FromStream(stream);

finish:

	if(stream != NULL)
	{
		stream->Release();
		stream = NULL;
	}

	if(global_handle != NULL)
	{
		GlobalFree(global_handle);
		global_handle = NULL;
	}

	return image;
}
UIGdiplusImageManager::UIGdiplusImageManager()
{

}

UIGdiplusImageManager::~UIGdiplusImageManager()
{
	for(image_info_for_stbs_ptrs::iterator iter=image_infos_.begin(); iter!=image_infos_.end(); iter++)
	{
		UIImageInfoData* image_info = iter->second;
		if(image_info == NULL)
			continue;
		if(image_info->image_h_ != NULL)
		{
			delete (Gdiplus::Image*)image_info->image_h_;
			image_info->image_h_ = NULL;
		}
		delete image_info;
	}
	image_infos_.clear();
}

const tchar* UIGdiplusImageManager::GetImageType()
{
	return _T("gidplus_image");
}

UIImageD UIGdiplusImageManager::GetImage(const tstring &img_name)
{
	image_info_for_stbs_ptrs::iterator iter = image_infos_.find(img_name);
	if(iter != image_infos_.end())
	{
		return UIImageD(GetImageType(), (void*)iter->second);
	}

	if(disk_manager_ == NULL)
		return UIImageD();

	ssbin file_buffer;
	if(disk_manager_->GetFileBuffer(img_name.c_str(), file_buffer, 0) == NULL)
		return UIImageD();

	Gdiplus::Image* image_handle = load_image_from_memory(file_buffer.ptr(), file_buffer.size());
	if(image_handle == NULL)
		return UIImageD();

	UIImageInfoData *ret = new UIImageInfoData;
	ret->image_h_ = image_handle;;
	ret->cx = image_handle->GetWidth();
	ret->cy = image_handle->GetHeight();
	image_infos_[img_name] = ret;
	return UIImageD(GetImageType(), ret);
}

bool UIGdiplusImageManager::CheckPresetImageInfo(const UIPresetImage &preset_img, UIPresetImageInfo &info)
{
	info.cx = 0;
	info.cy = 0;

	UIImageD image = GetImage(preset_img.image_name);
	if(image.image == NULL)
		return false;
	SS_ASSERT(image.image_type == GetImageType());
	UIImageInfoData *image_info = static_cast<UIImageInfoData*>(image.image);
	if(image_info == NULL)
		return false;

	if(!CheckImageDInfo(image, info))
		return false;

	if(preset_img.image_src_rect.Width() > 0 && preset_img.image_src_rect.Width() < info.cx)
		info.cx = preset_img.image_src_rect.Width();
	if(preset_img.image_src_rect.Height() > 0 && preset_img.image_src_rect.Height() < info.cy)
		info.cy = preset_img.image_src_rect.Height();
	return true;
}

bool UIGdiplusImageManager::CheckImageDInfo(const UIImageD &img_data, UIPresetImageInfo &info)
{
	info.cx = 0;
	info.cy = 0;

	SS_ASSERT(img_data.image_type == GetImageType());
	UIImageInfoData *image_info = static_cast<UIImageInfoData*>(img_data.image);
	if(image_info == NULL)
		return false;

	info.cx = image_info->cx;
	info.cy = image_info->cy;

	return true;
}

UIImageD UIGdiplusImageManager::GenerateImageFromHandle(HBITMAP bitmap)
{
	BITMAP bm = {0};
	if(::GetObject(bitmap, sizeof(bm), &bm) != sizeof(BITMAP))
		return UIImageD();
	SS_ASSERT(bm.bmBitsPixel == 32);

	BYTE *source = (BYTE*)bm.bmBits;

	Gdiplus::Bitmap* bitmap_plus = new Gdiplus::Bitmap(bm.bmWidth, bm.bmHeight,
		PixelFormat32bppARGB);
	if(bitmap_plus == NULL || bitmap_plus->GetLastStatus() != 0)
	{
		return UIImageD();
	}
	Gdiplus::BitmapData datas;
	Gdiplus::Rect rc(0, 0, bm.bmWidth, bm.bmHeight);
	bitmap_plus->LockBits(&rc, Gdiplus::ImageLockModeWrite,
		PixelFormat32bppARGB, &datas);
	byte *dest = (byte*)(datas.Scan0);
	for(int y=0; y<bm.bmHeight; y++)
	{
		memcpy(dest + (y*bm.bmWidthBytes), source+((bm.bmHeight-y-1)*bm.bmWidthBytes),
			bm.bmWidthBytes);
	}

	bitmap_plus->UnlockBits(&datas);

	UIImageInfoData *image_data = new UIImageInfoData;
	image_data->image_h_ = (void*)bitmap_plus;

	return UIImageD(GetImageType(), image_data);
}

void UIGdiplusImageManager::ReleaseImage(UIImageD &img)
{
	if(img.image_type != GetImageType())
		return;
	if(img.image == NULL)
		return;
	UIImageInfoData *image_data = (UIImageInfoData*)img.image;
	Gdiplus::Bitmap* bitmap_plus = (Gdiplus::Bitmap*)image_data->image_h_;
	if(bitmap_plus != NULL)
		delete bitmap_plus;
	delete image_data;
	return;
}

IUIDiskFilesManagerInterfaceAutoPtr UIGdiplusImageManager::SetDiskFilesManager(IUIDiskFilesManagerInterface * disk_man )
{
	IUIDiskFilesManagerInterfaceAutoPtr ret = disk_manager_;
	disk_manager_ = disk_man;
	return ret;
}

IUIDiskFilesManagerInterfaceAutoPtr UIGdiplusImageManager::GetDiskFilesManager()
{
	return disk_manager_;
}

_SSUIL_END
_SSL_END

